
#include "DXUT.h"
#include "SDKmisc.h"

#include <vector>
using namespace std;

#ifndef INPUT 
#define INPUT
namespace Input
{
  enum Buttons
  {
    ICB_Unknown,
    ICB_Left,
    ICB_Right,
    ICB_Up,
    ICB_Down,
    //
    ICB_PageUp,
    ICB_PageDown,
    //
    ICB_Addition,
    ICB_Subtraction,
    //
    ICB_F1,
    ICB_F2,
    ICB_F3,
    ICB_F4,
    //
    ICB_FINAL
  };
  enum ButtonsState
  {
    ICBS_Unknown,
    ICBS_Pressed,
    ICBS_Released,
  };
  class Message
  { 
  public:
    Buttons Button;
    ButtonsState State;
    UINT64 Time;
    Message()
    {
      Button = ICB_Unknown;
      State = ICBS_Unknown;
      Time = 0;
    }
    Message(Buttons button, ButtonsState state)
    {
      Button = button;
      State = state;
      Time = DXUTGetTime();
    }
  };
  class WindowsMessage : public Message
  {
  public:
    WindowsMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
      //Buttons (see http://msdn.microsoft.com/en-us/library/ms927178.aspx ):
      switch( wParam )
      {
      case VK_LEFT  : Button = ICB_Left;  break; 
      case VK_UP    : Button = ICB_Up;    break;
      case VK_RIGHT : Button = ICB_Right; break;
      case VK_DOWN  : Button = ICB_Down;  break;
      //
      case VK_PRIOR : Button = ICB_PageUp;    break;
      case VK_NEXT  : Button = ICB_PageDown;  break;
      //
      case VK_ADD      : Button = ICB_Addition;    break; // "+"
      case VK_SUBTRACT : Button = ICB_Subtraction; break; // "-"
      //
      case VK_F1    : Button = ICB_F1;    break; 
      case VK_F2    : Button = ICB_F2;    break;
      case VK_F3    : Button = ICB_F3;    break;
      case VK_F4    : Button = ICB_F4;    break;
      }
      
      //States:
      if( WM_KEYDOWN == uMsg )
        State = ICBS_Pressed;
      else if( WM_KEYDOWN == uMsg )
        State = ICBS_Released;

      //Time:
      Time = DXUTGetTime();
    }
  };
  class IListener
  {
  public:
    virtual void OnInputMessage(Message &message)=0;
  };
  class Controller
  {
    vector<Message> Messages;
    vector<IListener *> Listeners;
    //Singletone:
    static Controller* pController;  
  public:
    Controller() { }
    void AddListener(IListener *plistener)
    {
      Listeners.push_back(plistener);
    }
    void PushButton(Buttons button, ButtonsState state)
    {
      Message message(button, state);
      Messages.push_back(message);
    }
    void PushMessage(Message message)
    {
      Messages.push_back(message);
    }
    void ProcessMessages()
    {
      for(UINT64 i=0; i<Listeners.size(); i++)
      {
        for(UINT64 j=0; j<Messages.size(); j++)
        {
           Listeners[i]->OnInputMessage(Messages[j]);
        }
      }
      Messages.resize(0); //Processing complited;
    }
    static Controller* GetInstance();
  };
}
#endif /* INPUT */